//
//  SEOnlineReserveViewController.swift
//  SmartEyeForPatient
//
//  Created by QDSG on 2021/4/6.
//

import UIKit
import Photos

let kSEOnlineReserveHeaderDefaultHeight: CGFloat = 80 + UIScreen.navigationBarMaxY

class SEOnlineReserveViewController: SEBaseViewController {
    
    private var viewModel = SEInquiryInfoViewModel(withLoading: true) {
        didSet {
            tableView.reloadData()
        }
    }
    
    private var uploadVM = SEUploadViewModel(withLoading: true)
    
    convenience init(doctorDetailVM: SEDoctorDetailViewModel, examineRecordVm: SEExamineRecordViewModel = SEExamineRecordViewModel(), patientInfo: SEPatientDetailViewModel = SEPatientDetailViewModel()) {
        self.init()
        self.viewModel.doctorDetail = doctorDetailVM.model
        self.viewModel.info.picList = examineRecordVm.imageDTOList
        self.viewModel.info.illness = examineRecordVm.resultDTODescription
        self.viewModel.patientInfo = patientInfo
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        viewModel.confirmOnlineReserveSuccess = { [weak self] status in
            switch status {
            case .success:
                self?.pushToConfirmReserveAndPayVC()
            case .auth:
                self?.presentLoginViewController(selector: nil)
            case .failure:
                break
            }
        }
        
        uploadVM.updateData = { [weak self] status in
            guard let model = self?.uploadVM.fileModel else { return }
            switch status {
            case .success:
                self?.viewModel.addImage(with: model)
                self?.tableView.reloadData {
                    self?.tableView.scrollToBottom(animated: true)
                }
            case .auth:
                self?.presentLoginViewController(selector: nil)
            case .failure: break
            }
        }
        
        confirmView.viewIntroductionClosure = {
            let introductionView = UINib.loadViewFrom(SEGraphicalIntroductionView.self)
            introductionView.show()
        }
        confirmView.confirmReservationClosure = { [weak self] in
            if self?.checkPatientConditionDidFillin() == true {
                self?.viewModel.confirmOnlineReserveInfo()
            }
        }
    }
    
    override func setupUI() {
        navBarStyle = .clear
    }
    
    override func setupNavBar() {
        super.setupNavBar()
        navigationController?.navBarStyle(navBarStyle)
    }
    
    private lazy var headerView: SEOnlineReserveHeader = {
        let view = UINib.loadViewFrom(SEOnlineReserveHeader.self)
        view.attentionHandler = {
            self.pushToDoctorDetail()
        }
        return view
    }()

    @IBOutlet private weak var tableView: UITableView! {
        didSet {
            tableView.backgroundColor = UIColor.background
            tableView.tableFooterView = UIView()
            
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
            tapGesture.cancelsTouchesInView = false
            tableView.addGestureRecognizer(tapGesture)
            
            tableView.register(SEOnlineReserveHospitalCell.nibForCell(),
                               forCellReuseIdentifier: SEOnlineReserveHospitalCell.reuseIdentifier())
            tableView.register(SEOnlineReserveNameCell.nibForCell(),
                               forCellReuseIdentifier: SEOnlineReserveNameCell.reuseIdentifier())
            tableView.register(SEOnlineReserveAllergyHistoryCell.nibForCell(),
                               forCellReuseIdentifier: SEOnlineReserveAllergyHistoryCell.reuseIdentifier())
            tableView.register(SEOnlineReserveImageCell.nibForCell(),
                               forCellReuseIdentifier: SEOnlineReserveImageCell.reuseIdentifier())
            tableView.register(SEOnlineReserveTextCell.nibForCell(),
                               forCellReuseIdentifier: SEOnlineReserveTextCell.reuseIdentifier())
        }
    }
    
    @IBOutlet private weak var confirmView: SEOnlineReserveIntroduceButtonView!

}

extension SEOnlineReserveViewController {
    private func checkPatientConditionDidFillin() -> Bool {
        if !viewModel.patientDidPicked {
            SEHUD.show(message: "请先选择就诊人")
            return false
        }
        if viewModel.onlineReserveInfoAllEmpty {
            SEHUD.show(message: "就诊信息没填")
            return false
        }
        if viewModel.conditionDescEmpty {
            SEHUD.show(message: "病情描述没填")
            return false
        }
        if viewModel.allergyHistoryEmpty {
            SEHUD.show(message: "过敏史没填")
            return false
        }
        if viewModel.pastHistoryEmpty {
            SEHUD.show(message: "既往史没填")
            return false
        }
        return true
    }
}

// MARK: - Action Events

extension SEOnlineReserveViewController {
    @objc private func dismissKeyboard() {
        tableView.endEditing(true)
    }
    
    /// 跳转 确认预约 支付
    private func pushToConfirmReserveAndPayVC() {
        let confirmReserveVc = SEConfirmReserveViewController(inquiryId: viewModel.info.id ?? "", fromType: .hospitalizeReserve)
        confirmReserveVc.title = "确认预约"
        removeCurrentVcWhenPush(confirmReserveVc)
    }
    
    /// 跳转 医院主页
    private func pushToHospitalHomepage() {
        let vc = SEHospitalDetailViewController(with: viewModel.doctorDetail.hospitalId ?? "")
        navigationController?.pushViewController(vc, animated: true)
    }

    /// 跳转 医生主页
    private func pushToDoctorDetail() {
        let vc = SEDoctorDetailViewController(with: viewModel.doctorDetail.id ?? "")
        navigationController?.pushViewController(vc, animated: true)
    }
    
    /// 跳转 就诊人
    private func pushToPickPatientVC() {
        let vc = SEPatientListViewController(with: .select)
        navigationController?.pushViewController(vc, animated: true)
        vc.selectedHandler = { model in
            self.viewModel.patientInfo = model
            self.tableView.reloadData()
        }
    }
}

// MARK: - SEOnlineReserveImageCellDelegate

extension SEOnlineReserveViewController: SEOnlineReserveImageCellDelegate {
    func imageCell(_ cell: SEOnlineReserveImageCell, toImagePickerWith viewModel: SEInquiryInfoViewModel) {
        guard checkPatientConditionDidFillin() == true else { return }
        
        SEAlert.showImagePickerSheet(in: self) { _ in
            self.checkCameraPermission()
        } photoHandler: { _ in
            self.openPhotoLibrary()
        }
    }
    
    func imageCell(_ cell: SEOnlineReserveImageCell, deleteImageWith viewModel: SEInquiryInfoViewModel) {
        self.viewModel = viewModel
    }
}

// MARK: - UIImagePickerControllerDelegate

extension SEOnlineReserveViewController {
    private func checkCameraPermission() {
        let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
        switch authStatus {
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { (granted) in
                if !granted {
                    dispatch_async_safely_main_queue {
                        SEAlert.show(in: self.navigationController,
                                     title: "无法访问您的相机",
                                     message: "请到设置 -> 隐私 -> 相机 ，打开访问权限",
                                     confirmTitle: "去设置") { _ in
                            SEOpenSettingURL()
                        }
                    }
                }
            }
        case .restricted, .denied:
            SEAlert.show(in: self.navigationController,
                         title: "无法访问您的相机",
                         message: "请到设置 -> 隐私 -> 相机 ，打开访问权限",
                         confirmTitle: "去设置") { _ in
                SEOpenSettingURL()
            }
        case .authorized:
            openCamera()
        default:
            break
        }
    }
    
    private func openCamera() {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .camera
        present(imagePicker, animated: true, completion: nil)
    }
    
    private func openPhotoLibrary() {
        UIScrollView.appearance().contentInsetAdjustmentBehavior = .automatic
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .photoLibrary
        imagePicker.modalPresentationStyle = .custom
        present(imagePicker, animated: true, completion: nil)
    }
}

extension SEOnlineReserveViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            uploadVM.uploadImage(bucket: "A", type: "A-9", image: image, size: image.imageSize())
        }
        dismiss(animated: true) {
            UIScrollView.appearance().contentInsetAdjustmentBehavior = .never
        }
    }
}

// MARK: - UITableViewDataSource

extension SEOnlineReserveViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return viewModel.numberOfSectionsForOnlineReserve
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch indexPath.section {
        case 0:
            let cell = tableView.dequeueReusableCell(withIdentifier: SEOnlineReserveHospitalCell.reuseIdentifier()) as! SEOnlineReserveHospitalCell
            cell.update(with: viewModel)
            return cell
        case 1:
            let cell = tableView.dequeueReusableCell(withIdentifier: SEOnlineReserveNameCell.reuseIdentifier()) as! SEOnlineReserveNameCell
            cell.update(with: viewModel)
            return cell
        case 2, 4:
            let cell = tableView.dequeueReusableCell(withIdentifier: SEOnlineReserveTextCell.reuseIdentifier(), for: indexPath) as! SEOnlineReserveTextCell
            cell.update(with: viewModel, indexPath: indexPath) { viewModel in
                self.viewModel = viewModel
            }
            return cell
        case 3:
            let cell = tableView.dequeueReusableCell(withIdentifier: SEOnlineReserveAllergyHistoryCell.reuseIdentifier()) as! SEOnlineReserveAllergyHistoryCell
            cell.update(with: viewModel) { viewModel in
                self.viewModel = viewModel
            }
            return cell
        case 5:
            let cell = tableView.dequeueReusableCell(withIdentifier: SEOnlineReserveImageCell.reuseIdentifier()) as! SEOnlineReserveImageCell
            cell.delegate = self
            cell.update(with: viewModel)
            return cell
        default:
            return UITableViewCell()
        }
    }
}

// MARK: - UITableViewDelegate

extension SEOnlineReserveViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)
        switch indexPath.section {
        case 0: pushToHospitalHomepage()
        case 1: pushToPickPatientVC()
        case 2, 3, 4:
            if !viewModel.patientDidPicked {
                SEHUD.show(message: "请先选择就诊人")
            }
        default:
            break
        }
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        switch section {
        case 0:
            headerView.update(with: viewModel)
            return headerView
        case 3:
            let header = UINib.loadViewFrom(SEAllergyHistoryHeader.self)
            header.update(with: viewModel) { viewModel in
                self.viewModel = viewModel
            }
            return header
        default:
            return nil
        }
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return viewModel.headerHeightForOnlineReserve(in: section)
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 10
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return viewModel.cellHeightForOnlineReserve(at: indexPath)
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y > 0 {
            navBarStyle = .theme()
            navigationItem.title = viewModel.doctorDetail.name
        } else {
            navBarStyle = .clear
            navigationItem.title = "就诊信息填写"
        }
        navigationController?.navBarStyle(navBarStyle)
    }
}
